package homework.manager;

import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class SessionManager {
    //customerId => Session
    private final ConcurrentMap<String, Session> customerIdMap = new ConcurrentHashMap<>();
    //sessionKey => Session
    private final ConcurrentMap<String, Session> sessionKeyMap = new ConcurrentHashMap<>();

    public String getSessionKey(String customerId) {
        Session session = customerIdMap.computeIfAbsent(customerId, k -> new Session(customerId));
        if (session.isExpired()) {
            synchronized (customerId.intern()) {
                if(customerIdMap.get(customerId) == session) {
                    sessionKeyMap.remove(session.getKey());
                    session = new Session(customerId);
                    customerIdMap.put(customerId, session);
                } else {
                    session = customerIdMap.get(customerId);
                }
            }
        }
        sessionKeyMap.put(session.getKey(), session);

        return session.getKey();
    }

    public boolean isValidSession(String sessionKey) {
        Session session = sessionKeyMap.get(sessionKey);
        return session != null && !session.isExpired();
    }

    public String getCustomerId(String sessionKey) {
        Session session = sessionKeyMap.get(sessionKey);
        if(session != null && !session.isExpired()) {
            return session.customerId;
        }
        return null;
    }

    private static class Session {
        private final String key;
        private final String customerId;
        private final long creationTime;

        public Session(String customerId) {
            this.customerId = customerId;
            this.key = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8).toUpperCase();
            this.creationTime = System.currentTimeMillis();
        }

        public String getKey() {
            return key;
        }

        public boolean isExpired() {
            return System.currentTimeMillis() - creationTime > 10 * 60 * 1000;
        }
    }
}